{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "### TABLE A2 (Appendices)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded: jcr_mutiny_conflict_data.dta  |  Rows=1,599,624  Cols=94\n",
      "After lag-drop for lag models: 1,559,628 rows\n",
      "\\begin{table}\n",
      "\\caption{}\n",
      "\\label{}\n",
      "\\begin{center}\n",
      "\\begin{tabular}{lllllll}\n",
      "\\hline\n",
      "                   & m1        & m2        & m3        & m4        & m5        & m6         \\\\\n",
      "\\hline\n",
      "Military mutiny          & 0.499***  & 0.500***  & 0.499***  &           &           &            \\\\\n",
      "                   & (0.098)   & (0.098)   & (0.116)   &           &           &            \\\\\n",
      "Military mutiny\\_lag1    &           &           &           & 0.283***  & 0.304***  & 0.491***   \\\\\n",
      "                   &           &           &           & (0.109)   & (0.109)   & (0.121)    \\\\\n",
      "Military spending per soldier (logged) & -0.085*** & -0.091*** & -0.132*** & -0.067*** & -0.072*** & -0.108***  \\\\\n",
      "                   & (0.018)   & (0.018)   & (0.022)   & (0.018)   & (0.018)   & (0.023)    \\\\\n",
      "Years since last coup & 0.007***  & 0.007***  & 0.004     & 0.007***  & 0.006***  & 0.003      \\\\\n",
      "                   & (0.002)   & (0.002)   & (0.003)   & (0.002)   & (0.002)   & (0.003)    \\\\\n",
      "Civil conflict  & 0.566***  & 0.566***  & 0.499***  & 0.595***  & 0.595***  & 0.524***   \\\\\n",
      "                   & (0.058)   & (0.059)   & (0.071)   & (0.058)   & (0.058)   & (0.071)    \\\\\n",
      "Defense alliance    & -0.231*** & -0.214*** & -0.164*** & -0.247*** & -0.230*** & -0.181***  \\\\\n",
      "                   & (0.049)   & (0.050)   & (0.059)   & (0.050)   & (0.050)   & (0.060)    \\\\\n",
      "Capability ratio            & 0.559***  & 0.565***  & 0.362***  & 0.588***  & 0.595***  & 0.411***   \\\\\n",
      "                   & (0.059)   & (0.060)\n",
      "...\n",
      "\n",
      "LaTeX table written to: C:\\Users\\rmuhi\\OneDrive\\Desktop\\Mutiny_Conflict Paper_All\\Replication File\\logit_results_table.tex\n"
     ]
    }
   ],
   "source": [
    "# ----------------------------------------------------------\n",
    "# 0) Lightweight installer if packages are missing\n",
    "# ----------------------------------------------------------\n",
    "\n",
    "try:\n",
    "    import pandas as _pd; import statsmodels as _sm; import matplotlib as _mpl\n",
    "except Exception:\n",
    "    import sys, subprocess\n",
    "    subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-U\", \"pandas\", \"statsmodels\", \"matplotlib\"])\n",
    "\n",
    "from pathlib import Path\n",
    "import pandas as pd\n",
    "import statsmodels.formula.api as smf\n",
    "from statsmodels.iolib.summary2 import summary_col\n",
    "\n",
    "\n",
    "# ----------------------------\n",
    "# 1) Load data\n",
    "# ----------------------------\n",
    "file_path = Path(r\"C:\\Users\\rmuhi\\OneDrive\\Desktop\\Mutiny_Conflict Paper_All\\Replication File\\jcr_mutiny_conflict_data.dta\")\n",
    "if not file_path.exists():\n",
    "    raise FileNotFoundError(f\"Could not find .dta file at: {file_path}\")\n",
    "\n",
    "data = pd.read_stata(file_path)\n",
    "print(f\"Loaded: {file_path.name}  |  Rows={len(data):,}  Cols={len(data.columns)}\")\n",
    "\n",
    "\n",
    "# ----------------------------\n",
    "# 2) Create lags \n",
    "# ----------------------------\n",
    "data = data.sort_values(['id','year'])\n",
    "\n",
    "data['mutiny_t_lag1'] = data.groupby('id')['mutiny_t'].shift(1)\n",
    "data['violent_t_lag1'] = data.groupby('id')['violent_t'].shift(1)\n",
    "data['size_t_b_lag1'] = data.groupby('id')['size_t_b'].shift(1)\n",
    "data['mduration_t_cat3_lag1'] = data.groupby('id')['mduration_t_cat3'].shift(1)\n",
    "\n",
    "# A stricter sample for lagged RHS models to avoid missingness\n",
    "data_lagged = data.dropna(subset=['violent_t_lag1','size_t_b_lag1','mduration_t_cat3_lag1'])\n",
    "print(f\"After lag-drop for lag models: {len(data_lagged):,} rows\")\n",
    "\n",
    "\n",
    "# ----------------------------\n",
    "# 3) Model formulas\n",
    "# ----------------------------\n",
    "formula1 = 'dispute ~ mutiny_t + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula2 = 'dispute_hh3 ~ mutiny_t + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula3 = 'dispute_hh4 ~ mutiny_t + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "\n",
    "formula4 = 'dispute ~ mutiny_t_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula5 = 'dispute_hh3 ~ mutiny_t_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "formula6 = 'dispute_hh4 ~ mutiny_t_lag1 + lmmilex_persol_t + years_since_coup + ucdp_civconf_t2 + defense_target + capprop + jdem + majorpower + cold_war + t_since + t2_since + t3_since'\n",
    "\n",
    "\n",
    "# ----------------------------\n",
    "# 4) Fit helper (HC1-robust, with fallback)\n",
    "# ----------------------------\n",
    "def fit_logit_robust(formula, df):\n",
    "    model = smf.logit(formula, df)\n",
    "    try:\n",
    "        res = model.fit(disp=False, cov_type='HC1')\n",
    "    except TypeError:\n",
    "        res0 = model.fit(disp=False)\n",
    "        res = res0.get_robustcov_results(cov_type='HC1')\n",
    "    return res\n",
    "\n",
    "result1 = fit_logit_robust(formula1, data)\n",
    "result2 = fit_logit_robust(formula2, data)\n",
    "result3 = fit_logit_robust(formula3, data)\n",
    "result4 = fit_logit_robust(formula4, data_lagged)\n",
    "result5 = fit_logit_robust(formula5, data_lagged)\n",
    "result6 = fit_logit_robust(formula6, data_lagged)\n",
    "\n",
    "# ----------------------------\n",
    "# 5) Build LaTeX table\n",
    "# ----------------------------\n",
    "regressor_order = [\n",
    "    'mutiny_t',\n",
    "    'mutiny_t_lag1',\n",
    "    'lmmilex_persol_t',\n",
    "    'years_since_coup',\n",
    "    'ucdp_civconf_t2',\n",
    "    'defense_target',\n",
    "    'capprop',\n",
    "    'jdem',\n",
    "    'majorpower',\n",
    "    'cold_war',\n",
    "    'Intercept'  # will be renamed if shows as 'const'\n",
    "]\n",
    "\n",
    "info_dict = {\n",
    "    'N':         lambda x: f\"{int(x.nobs):d}\",\n",
    "    'Pseudo R²': lambda x: f\"{getattr(x, 'prsquared', float('nan')):.3f}\"\n",
    "}\n",
    "\n",
    "results = [result1, result2, result3, result4, result5, result6]\n",
    "\n",
    "tbl = summary_col(\n",
    "    results=results,\n",
    "    float_format='%0.3f',\n",
    "    stars=True,\n",
    "    model_names=['m1','m2','m3','m4','m5','m6'],\n",
    "    info_dict=info_dict,\n",
    "    regressor_order=regressor_order,\n",
    "    drop_omitted=True  # hide time polynomials from the body if not in order list\n",
    ")\n",
    "\n",
    "latex_lines = tbl.as_latex().splitlines()\n",
    "\n",
    "# Insert extra rows immediately after the Pseudo R² line\n",
    "insert_idx = next((i for i, ln in enumerate(latex_lines) if 'Pseudo R²' in ln), None)\n",
    "if insert_idx is not None:\n",
    "    checks = ' & ' + ' & '.join(['\\\\checkmark'] * len(results)) + r' \\\\'\n",
    "    for new_line in [r\"Time polynomials\" + checks, r\"Robust SE\" + checks]:\n",
    "        insert_idx += 1\n",
    "        latex_lines.insert(insert_idx, new_line)\n",
    "\n",
    "# Friendly labels (handle escaped & unescaped)\n",
    "replacements = {\n",
    "    'mutiny_t':                 'Military mutiny',\n",
    "    'mutiny\\\\_t':               'Military mutiny',\n",
    "    'mutiny_t_lag1':            'Military mutiny (t-1)',\n",
    "    'mutiny\\\\_t\\\\_lag1':        'Military mutiny (t-1)',\n",
    "    'lmmilex_persol_t':         'Military spending per soldier (logged)',\n",
    "    'lmmilex\\\\_persol\\\\_t':     'Military spending per soldier (logged)',\n",
    "    'years_since_coup':         'Years since last coup',\n",
    "    'years\\\\_since\\\\_coup':     'Years since last coup',\n",
    "    'ucdp_civconf_t2':          'Civil conflict',\n",
    "    'ucdp\\\\_civconf\\\\_t2':      'Civil conflict',\n",
    "    'defense_target':           'Defense alliance',\n",
    "    'defense\\\\_target':         'Defense alliance',\n",
    "    'capprop':                  'Capability ratio',\n",
    "    'jdem':                     'Both democracy',\n",
    "    'majorpower':               'Major power',\n",
    "    'cold_war':                 'Cold War',\n",
    "    'cold\\\\_war':               'Cold War',\n",
    "    'Intercept':                'Constant',\n",
    "    'const':                    'Constant'\n",
    "}\n",
    "\n",
    "fixed_lines = []\n",
    "for line in latex_lines:\n",
    "    for old, new in replacements.items():\n",
    "        if old in line:\n",
    "            line = line.replace(old, new)\n",
    "    fixed_lines.append(line)\n",
    "\n",
    "custom_latex = \"\\n\".join(fixed_lines)\n",
    "\n",
    "# Preview and save\n",
    "print(custom_latex[:1500] + \"\\n...\\n\")\n",
    "out_tex = file_path.parent / \"table_A2.tex\"\n",
    "out_tex.write_text(custom_latex, encoding=\"utf-8\")\n",
    "print(f\"LaTeX table written to: {out_tex}\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
